home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / CUCD / Magazine / C_Tutorial / Part-11 / req2 / idcmp.c < prev    next >
C/C++ Source or Header  |  1998-04-05  |  10KB  |  409 lines

  1. #include "idcmp.h"
  2. #include "drawwin.h"
  3. #include "gadgets.h"
  4. #include "loadsave.h"
  5. #include "menu.h"
  6. #include "toolwin.h"
  7. #include "arexx.h"
  8. #include "fractal.h"
  9.  
  10. #include<dos/rdargs.h>
  11.  
  12. #include<string.h>
  13. #include<stdio.h>
  14.  
  15. #include<clib/dos_protos.h>
  16. #include<clib/exec_protos.h>
  17. #include<clib/gadtools_protos.h>
  18. #include<clib/graphics_protos.h>
  19. #include<clib/intuition_protos.h>
  20.  
  21. static void doGadgetUp(struct Window*, UWORD, struct Gadget*);
  22. static int  doMenuPick(struct Window*, UWORD);
  23. static int  doARexx(struct RexxMsg*, struct Window*);
  24.  
  25. static void new(struct Window*);
  26.  
  27. static int  isCommand(char*, char*, char*, LONG*);
  28. static void freeCommand(void);
  29.  
  30. /* Our message handling code */
  31. void handleIDCMP()
  32. {
  33.     char* text = "Hello World!";
  34.     int going = TRUE;
  35.     int drawing = FALSE;
  36.     ULONG drawsig, toolsig, arexxsig, gotsig;
  37.     struct Window* drawwin = getDrawWin();
  38.     drawsig = 1 << drawwin->UserPort->mp_SigBit;
  39.     arexxsig = getARexxSig();
  40.     while(going)
  41.     {
  42.         struct IntuiMessage* intuimsg;
  43.         /* Only include tool window signal mask if window is open */
  44.         toolsig = getToolSig();
  45.         /* Wait for messages to arrive */
  46.         gotsig = Wait(drawsig | toolsig | arexxsig);
  47.         /* Messages have arrived: loop through all of them */
  48.         /* Check messages from the drawing window first */
  49.         if(gotsig & drawsig)
  50.         {
  51.             while(intuimsg = GT_GetIMsg(drawwin->UserPort))
  52.             {
  53.                 /* Copy the important bits of the message */
  54.                 ULONG class = intuimsg->Class;
  55.                 UWORD code = intuimsg->Code;
  56.                 WORD mousex = intuimsg->MouseX;
  57.                 WORD mousey = intuimsg->MouseY;
  58.                 /* Reply when finished copying bits from message */
  59.                 GT_ReplyIMsg(intuimsg);
  60.                 /* Act on this message... */
  61.                 switch(class)
  62.                 {
  63.                 case IDCMP_MOUSEBUTTONS:
  64.                     switch(code)
  65.                     {
  66.                     case SELECTDOWN:
  67.                         drawing = TRUE;
  68.                         break;
  69.                     case SELECTUP:
  70.                         drawing = FALSE;
  71.                         break;
  72.                     }
  73.                     /* break; omitted so we draw on click, too */
  74.                 case IDCMP_MOUSEMOVE:
  75.                     if(drawing)
  76.                     {
  77.                         Move(drawwin->RPort, mousex, mousey);
  78.                         Text(drawwin->RPort, text, strlen(text));
  79.                         setModified(TRUE);
  80.                     }
  81.                     break;
  82.                 case IDCMP_MENUPICK:
  83.                     going = doMenuPick(drawwin, code);
  84.                     drawwin = getDrawWin();
  85.                     drawsig = 1 << drawwin->UserPort->mp_SigBit;
  86.                     break;
  87.                 }
  88.             }
  89.         }
  90.         /* Now check messages from the tool window */
  91.         if(going && (gotsig & toolsig))
  92.         {
  93.             struct Window* toolwin = getToolWin();
  94.             while(toolwin && (intuimsg = GT_GetIMsg(toolwin->UserPort)))
  95.             {
  96.                 /* Copy the important bits of the message */
  97.                 ULONG class = intuimsg->Class;
  98.                 UWORD code = intuimsg->Code;
  99.                 APTR iaddr = intuimsg->IAddress;
  100.                 /* Reply when finished copying bits from message */
  101.                 GT_ReplyIMsg(intuimsg);
  102.                 /* Act on this message... */
  103.                 switch(class)
  104.                 {
  105.                 case IDCMP_CLOSEWINDOW:
  106.                     closeToolWin();
  107.                     /* Update our local toolwin, so we stop loop */
  108.                     toolwin = NULL;
  109.                     uncheckToolBar(drawwin);
  110.                     break;
  111.                 case IDCMP_REFRESHWINDOW:
  112.                     /* You *MUST* remember to ask for and handle these refresh messages */
  113.                     GT_BeginRefresh(toolwin);
  114.                     GT_EndRefresh(toolwin, TRUE);
  115.                     break;
  116.                 case IDCMP_GADGETUP:
  117.                     doGadgetUp(drawwin, code, (struct Gadget*)iaddr);
  118.                     break;
  119.                 case IDCMP_MENUPICK:
  120.                     going = doMenuPick(drawwin, code);
  121.                     /* Update our local toolwin, so we stop loop */
  122.                     toolwin = getToolWin();
  123.                     drawwin = getDrawWin();
  124.                     drawsig = 1 << drawwin->UserPort->mp_SigBit;
  125.                     break;
  126.                 }
  127.             }
  128.         }
  129.         /* Now check messages from the ARexx port */
  130.         if(going && (gotsig & arexxsig))
  131.         {
  132.             struct RexxMsg* msg;
  133.             while(going && (msg = getARexxMsg()))
  134.                 going = doARexx(msg, drawwin);
  135.         }
  136.     }
  137. }
  138.  
  139. /* Process IDCMP_GADGETUP event */
  140. static void doGadgetUp(struct Window* drawwin, UWORD code, struct Gadget* gad)
  141. {
  142.     switch(gad->GadgetID)
  143.     {
  144.     case MYBUT_ID:
  145.         /* Our button was clicked!  Set foreground to next pen colour */
  146.         nextFgPen(drawwin);
  147.         break;
  148.     case MYPAL_ID:
  149.         /* Our palette gadget was clicked!  Set foreground to gadget colour */
  150.         setFgPen(drawwin, code);
  151.         break;
  152.     }
  153. }
  154.  
  155. /* Process IDCMP_MENUPICK event */
  156. static int doMenuPick(struct Window* drawwin, UWORD code)
  157. {
  158.     UWORD menuCode, menuNumber, itemNumber;
  159.     /* Loop over all the menu selections in the menu code */
  160.     struct MenuItem* item;
  161.     for(menuCode = code;
  162.             menuCode != MENUNULL;
  163.             menuCode = item->NextSelect)
  164.     {
  165.         item = ItemAddress(drawwin->MenuStrip, menuCode);
  166.         /* Extract the menu number and menu item number from the menu code */
  167.         menuNumber = MENUNUM(menuCode);
  168.         itemNumber = ITEMNUM(menuCode);
  169.         /* Now decide what to do based on what menu item was selected */
  170.         switch(menuNumber)
  171.         {
  172.         case 0:  /* Project menu */
  173.             switch(itemNumber)
  174.             {
  175.             case 0:  /* Load */
  176.                 {
  177.                     struct EasyStruct myreq = { sizeof(struct EasyStruct),
  178.                                                                             0,
  179.                                                                             "Overwrite Confirmation",
  180.                                                                             "Do you really wish to overwrite the current image?",
  181.                                                                             "Yes|No" };
  182.                     /* If the image isn't modified we don't need to ask... */
  183.                     if(!isModified() || EasyRequest(drawwin, &myreq, NULL))
  184.                     {
  185.                         return load();
  186.                     }
  187.                 }
  188.                 break;
  189.             case 1:  /* Save */
  190.                 save();
  191.                 break;
  192.             case 3:  /* New (item 2 is the bar!) */
  193.                 {
  194.                     struct EasyStruct myreq = { sizeof(struct EasyStruct),
  195.                                                                             0,
  196.                                                                             "Erase Confirmation",
  197.                                                                             "Do you really wish to clear the current image?",
  198.                                                                             "Yes|No" };
  199.                     /* If the image isn't modified we don't need to ask... */
  200.                     if(!isModified() || EasyRequest(drawwin, &myreq, NULL))
  201.                     {
  202.                         new(drawwin);
  203.                     }
  204.                 }
  205.                 break;
  206.             case 5:  /* About (item 4 is the bar!) */
  207.                 {
  208.                     struct EasyStruct myreq = { sizeof(struct EasyStruct),
  209.                                                                             0,
  210.                                                                             "About",
  211.                                                                             "HelloPainter v11.2\n"
  212.                                                                                 "Brought to you by CU Amiga",
  213.                                                                             "OK" };
  214.                     EasyRequest(drawwin, &myreq, NULL);
  215.                 }
  216.                 break;
  217.             case 7:  /* Quit (item 6 is the bar!) */
  218.                 {
  219.                     struct EasyStruct myreq = { sizeof(struct EasyStruct),
  220.                                                                             0,
  221.                                                                             "Exit Confirmation",
  222.                                                                             "Do you really wish to quit?",
  223.                                                                             "Yes|No" };
  224.                     /* If the image isn't modified we don't need to ask... */
  225.                     if(!isModified() || EasyRequest(drawwin, &myreq, NULL))
  226.                         return FALSE;
  227.                 }
  228.                 break;
  229.             }
  230.             break;
  231.         case 1:  /* Pen menu */
  232.             switch(itemNumber)
  233.             {
  234.             case 0:  /* Next */
  235.                 nextFgPen(drawwin);
  236.                 break;
  237.             case 1:  /* Prev */
  238.                 prevFgPen(drawwin);
  239.                 break;
  240.             case 3:  /* Reset (item 2 is the bar!) */
  241.                 resetFgPen(drawwin);
  242.                 break;
  243.             }
  244.             break;
  245.         case 2:  /* Tools menu */
  246.             switch(itemNumber)
  247.             {
  248.             case 0:  /* Screen Bar */
  249.                 ShowTitle(drawwin->WScreen, item->Flags & CHECKED);
  250.                 break;
  251.             case 1:  /* Tool Bar */
  252.                 /* Do the open or close */
  253.                 if(item->Flags & CHECKED)
  254.                 {
  255.                     /* If the open fails, stop immediately */
  256.                     if(!openToolWin())
  257.                         return FALSE;
  258.                 }
  259.                 else
  260.                     closeToolWin();
  261.                 break;
  262.             case 3:  /* Fractal (item 2 is the bar!) */
  263.                 drawFractal(drawwin);
  264.             }
  265.         }
  266.     }
  267.     /* Keep going */
  268.     return TRUE;
  269. }
  270.  
  271. static void new(struct Window* win)
  272. {
  273.     SetRast(win->RPort, 0);
  274.     setModified(FALSE);
  275. }
  276.  
  277. /* Our RDArgs structure for use with ReadArgs() */
  278. static struct RDArgs* myrdargs = NULL;
  279.  
  280. int createArgs()
  281. {
  282.     if(myrdargs = AllocDosObject(DOS_RDARGS, NULL))
  283.     {
  284.         /* Disable prompting on stdin when "?" is the argument */
  285.         myrdargs->RDA_Flags = RDAF_NOPROMPT;
  286.         return TRUE;
  287.     }
  288.     else
  289.         printf("Error: could not allocate args for ARexx commands\n");
  290.     return FALSE;
  291. }
  292.  
  293. void freeArgs()
  294. {
  295.     if(myrdargs)
  296.         FreeDosObject(DOS_RDARGS, myrdargs);
  297. }
  298.  
  299. /* The result of a ReadArgs() while parsing commands */
  300. static struct RDArgs* rdargs = NULL;
  301.  
  302. /* Test if a string matches a command, using ReadArgs() */
  303. static int isCommand(char* text, char* comm,
  304.                                          char* templ, LONG* args)
  305. {
  306.     int clen = strlen(comm);
  307.     if(strnicmp(text, comm, clen) == 0)
  308.     {
  309.         /* Is the command followed by some whitespace? */
  310.         if(text[clen] == ' ' || text[clen] == '\t')
  311.         {
  312.             int tlen = strlen(text);
  313.             /* Set up our myrdargs so we can use ReadArgs() */
  314.             myrdargs->RDA_Source.CS_Buffer = text+clen+1;
  315.             myrdargs->RDA_Source.CS_Length = tlen-clen;
  316.             myrdargs->RDA_Source.CS_CurChr = 0;
  317.             myrdargs->RDA_DAList = NULL;
  318.             myrdargs->RDA_Buffer = NULL;
  319.             /* Temporarily end the string with a return... */
  320.             /* (Needed to get ReadArgs() to work properly) */
  321.             text[tlen] = '\n';
  322.             rdargs = ReadArgs(templ, args, myrdargs);
  323.             /* ... now we must reinstate the string's terminator */
  324.             text[tlen] = '\0';
  325.             return rdargs != NULL;
  326.         }
  327.     }
  328.     return NULL;
  329. }
  330.  
  331. static void freeCommand()
  332. {
  333.     if(rdargs)
  334.     {
  335.         FreeArgs(rdargs);
  336.         rdargs = NULL;
  337.     }
  338. }
  339.  
  340. /* The maximum number of arguments for our commands */
  341. #define MAX_ARGS (3)
  342.  
  343. #define COMM_QUIT        "QUIT"
  344.  
  345. #define COMM_NEW        "NEW"
  346.  
  347. #define COMM_PEN        "PEN"
  348. #define TEMPL_PEN        "PEN/N"
  349. enum PEN_ARGS { PEN_PEN };
  350.  
  351. #define COMM_DRAW        "DRAW"
  352. #define TEMPL_DRAW    "X/N,Y/N,TEXT/F"
  353. enum DRAW_ARGS { DRAW_X, DRAW_Y, DRAW_TEXT };
  354.  
  355. /* Process an ARexx message */
  356. static int doARexx(struct RexxMsg* msg, struct Window* drawwin)
  357. {
  358.     int going = TRUE;
  359.     /* By default, our reply will indicate an error */
  360.     LONG rc = 20;
  361.     char* res = NULL;
  362.     char* command = msg->rm_Args[0];
  363.     /* Parse the command */
  364.     if(stricmp(command, COMM_QUIT) == 0)
  365.     {
  366.         going = FALSE;
  367.         /* We recognised the command, so set rc to zero */
  368.         rc = 0;
  369.         res = "Hello Painter is quitting";
  370.     }
  371.     else if(stricmp(command, COMM_NEW) == 0)
  372.     {
  373.         new(drawwin);
  374.         rc = 0;
  375.         res = "Display cleared";
  376.     }
  377.     else
  378.     {
  379.         LONG args[MAX_ARGS];
  380.         int i;
  381.         for(i=0; i<MAX_ARGS; i++)
  382.             args[i] = NULL;
  383.         if(isCommand(command, COMM_PEN, TEMPL_PEN, args))
  384.          {
  385.             /* args[0] holds the pen number to use */
  386.             LONG* nptr = (LONG*)(args[PEN_PEN]);
  387.             setFgPen(drawwin, *nptr);
  388.             rc = 0;
  389.             res = "Pen set";
  390.         }
  391.         else if(isCommand(command, COMM_DRAW, TEMPL_DRAW, args))
  392.          {
  393.             /* args[DRAW_X] and args[DRAW_Y] hold the coordinate */
  394.             /* args[DRAW_TEXT] holds the text to be drawn */
  395.             LONG* xptr = (LONG*)(args[DRAW_X]);
  396.             LONG* yptr = (LONG*)(args[DRAW_Y]);
  397.             char* text = (char*)(args[DRAW_TEXT]);
  398.             Move(drawwin->RPort, *xptr, *yptr);
  399.             Text(drawwin->RPort, text, strlen(text));
  400.             setModified(TRUE);
  401.             rc = 0;
  402.             res = "Text drawn";
  403.         }
  404.         freeCommand();
  405.     }
  406.     replyARexxMsg(msg, rc, res);
  407.     return going;
  408. }
  409.